package gameoflive;

import java.util.HashMap;
import java.util.Map;

public class Cell
{
    private Point   position;
    
    private boolean alive;
    
    private boolean surviving;
    
     public enum NEIGHBORS
     {
         LEFT, TOPLEFT, TOP, TOPRIGHT, RIGHT,
         BOTTOMLEFT, BOTTOM, BOTTOMRIGHT
     }
    
    private Map<NEIGHBORS, Cell> neighbors = new HashMap<NEIGHBORS, Cell>();
    
    public void setNeighbor(NEIGHBORS neighbor, Cell cell)
    {
        this.neighbors.put(neighbor, cell);
    }
    
    public Point getNeighborPos(NEIGHBORS pos)
    {
        final int MAX_X = (int) GameOfLive.getInstance().getMaxXY().getWidth() - 1;
        final int MAX_Y = (int) GameOfLive.getInstance().getMaxXY().getHeight() - 1;
        // koordinaten
        int x = (int) position.getWidth();
        int y = (int) position.getHeight();
        // richtung
        switch (pos)
        {
            case RIGHT:
            {
                x++;
                if (x > MAX_X)
                {
                    x = 0;
                }
                break;
            }
            case BOTTOM:
            {
                y++;
                if (y > MAX_Y)
                {
                    y = 0;
                }
                break;
            }
            case LEFT:
            {
                x--;
                if (x < 0)
                {
                    x = MAX_X;
                }
                break;
            }
            case TOP:
            {
                y--;
                if (y < 0)
                {
                    y = MAX_Y;
                }
                break;
            }
            case BOTTOMLEFT:
            {
                x = (int) getNeighborPos(NEIGHBORS.LEFT).getWidth();
                y = (int) getNeighborPos(NEIGHBORS.BOTTOM).getHeight();
                break;
            }
            case BOTTOMRIGHT:
            {
                x = (int) getNeighborPos(NEIGHBORS.RIGHT).getWidth();
                y = (int) getNeighborPos(NEIGHBORS.BOTTOM).getHeight();
                break;
            }
            case TOPLEFT:
            {
                x = (int) getNeighborPos(NEIGHBORS.LEFT).getWidth();
                y = (int) getNeighborPos(NEIGHBORS.TOP).getHeight();
                break;
            }
            case TOPRIGHT:
            {
                x = (int) getNeighborPos(NEIGHBORS.RIGHT).getWidth();
                y = (int) getNeighborPos(NEIGHBORS.TOP).getHeight();
                break;
            }
        }
        return new Point(x, y);
    }
    
    public Cell getNeighbor(NEIGHBORS pos)
    {
        Cell neighbor = neighbors.get(pos);
        if (neighbor == null)
        {
            Point neighborPos = getNeighborPos(pos);
            neighbor = GameOfLive.getInstance().getCell(neighborPos);
            if (neighbor == null)
            {
                neighbor = new Cell((int) neighborPos.getWidth(), (int) neighborPos.getHeight(), false, false);
            }
            neighbors.put(pos, neighbor);
        }
        return neighbor;
    }
    
    public Cell(int x, int y, boolean alive, boolean surviving)
    {
        this.position = new Point(x, y);
        this.setAlive(alive);
        this.setSurviving(surviving);
    }
    
    public Point getPosition()
    {
        return position;
    }
    
    public void setPosition(Point position)
    {
        this.position = position;
    }
    
    public boolean isAlive()
    {
        return alive;
    }
    
    public void setAlive(boolean alive)
    {
        this.alive = alive;
    }
    
    public boolean isSurviving()
    {
        return surviving;
    }
    
    public void setSurviving(boolean surviving)
    {
        this.surviving = surviving;
    }
    
    public boolean hasAllNeighbors()
    {
        return neighbors.size() == NEIGHBORS.values().length;
    }
    
    public int countLivingNeighbors()
    {
        int livingNeighbors = 0;
        for (NEIGHBORS neighbor : NEIGHBORS.values())
        {
            if (getNeighbor(neighbor).isAlive())
            {
                livingNeighbors++;
            }
        }
        return livingNeighbors;
    }
    
    @Override
    public String toString()
    {
        StringBuilder s = new StringBuilder();
        s.append("alive=").append(isAlive());
        s.append("; surviving=").append(isSurviving());
        if (hasAllNeighbors())
        {
            s.append("; living neighbors=" + countLivingNeighbors());
        }
        else
        {
            s.append("; not enough neighbors");
        }
        s.append("; position=").append(position.toString());
        return s.toString();
    }
}
